<?xml version="1.0" encoding="utf-8"?>
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:blueonionsoftware-com:bloget:runtime:data">
  <text>One of the more troublesome incompatibilities between .Net and COM is matching COM's status code error handling mechanism with .Net's exception oriented error facility.  Luckily, Visual Studio provides tools to generate proxy code that allow us to easily import COM interfaces into .Net without worrying about the differences between the two error models.  Unlike COM in C++, the CLR automatically takes care of the QueryInterface, AddRef/Relase, and error handling for every method when we import a COM object into .Net.

When the CLR invokes a COM method, it examines the returned HRESULT.  If the HRESULT is less than zero, which indicates that the COM method failed, the CLR then wraps the HRESULT in a COMException object, pulls the error object out of GetErrorInfo, and throws the COMException object back to the .Net client.  The fact that the CLR is consuming the HRESULT begs the question, "if the HRESULT is gone, what is the return type for the function?"  The answer is that the CLR, in the tradition of languages like vb and jscript, rewrites the function signature to return the parameter marked as [out, retval] instead of returning the HRESULT.
&lt;code&gt;
//Sample IDL for IWebBrowser2::get_LocationURL
    [propget, id(1), helpstring("method get_LocationURL")] HRESULT get_LocationURL([out, retval] BSTR url);
        
//Sample C# invocation.
         string url = webBrowser.LocationURL;
&lt;/code&gt;

Since the method is marked as [propget], C# also strips the leading get_ from the method and allows us to use it like a native C# property.

This behavior works great for .Net calling into COM, but what about when COM calls into .Net? Suppose that we have instantiated a COM object in .Net that allows us to pass in a custom interface to let us override some default action.

The interface is defined with the following IDL snippet:
&lt;code&gt;
interface IOverrideMe : IUnknown
{
    [helpstring("method overrideA")] HRESULT overrideA(void);
    [helpstring("method overrideB")] HRESULT overrideB(void);
};
&lt;/code&gt;

We match it with the following C# snippet:
&lt;code&gt;
[ComImport, Guid("??????????-????-????-????-???????????????"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOverrideMe
{
   void overrideA();
   void overrideB();
}
&lt;/code&gt;

Notice that the interface has 3 attributes.  The [ComImport] attribute indicates that this interface matches up with an interface previously defined in a type library and it should treat it differently than a normal .Net interface.  The [Guid] attribute specifies the IID of the interface. The [InterfaceType] attribute indicates that this interface inherits from IUnknown.  The other options for [InterfaceType] are InterfaceIsDual and InterfaceIsIDispatch.

Now that we have the interface defined, we can write a C# class that implements it.  However, after reading the documentation for the IOverrideMe interface, we decide that we only want to override the overrideA method and we don't need to use overrideB.  To meet the requirements of the interface, we do have to implement both methods even though we aren't interested in overrideB.  The documentation states that we can return a custom HRESULT called W_OVERRIDE_DO_DEFAULT and the COM object won't complain.

Armed with this knowledge, we implement the interface in C#
&lt;code&gt;
using System.Runtime.InteropServices;

public class overrideImpl :  IOverrideMe
{
   private static Int32 S_OK = unchecked((int)0x00000000);
   private const int W_OVERRIDE_DO_DEFAULT = unchecked((int)0x8004FFFF);
   void overrideA()
   {
       //Do something interesting.
      
      Marshal.ThrowExceptionForHR(S_OK);
   }

   void overrideB()
   {
      Marshal.ThrowExceptionForHR(W_OVERRIDE_DO_DEFAULT);
   }
}
&lt;/code&gt;

Unfortunately, when we run the app in the debugger we get this error message:
&lt;img src='http://aabmag23a/devnotes/wp-content/COMException.jpg' alt='COM Exception Message' /&gt;
  
We know that we intend to return this error, but we really don't need the CLR reminding us about it by throwing an exception.  The problem is that the default logic of the runtime treats negative HRESULTs as an error.  While that is technically correct, it is problematic in our case because the W_OVERRIDE_DO_DEFAULT has its severity code (the first two bits of the HRESULT) set to warning (0x10) which the CLR interprets as negative and it throws an exception that it doesn't need to throw.   The COM object couldn't care less since it can only accept the HRESULT which means the exception is generated and suppressed in exchange for the HRESULT from the CLR.   Our code, the COM object, and the users of our program would never know that the exception existed.  The reason we see the exception is that the debugger hooks the exception at first chance and notifies us before allowing the CLR's default mechanism to suppress it. 

   Notice that the CLR doesn't generate an exception for overrideA.  This is because S_OK is defined as 0x00000000, which is interpreted as a positive HRESULT because the severity code is set to success (0x00).

  The workaround to this problem is to tell the CLR that we want to return a HRESULT.  This is accomplished by adding the attribute [PreserveSig] to each method that needs to directly return an HRESULT.  We also modify the return type to be a 32 bit int value, which is the same size and bit order as the platform HRESULT type.

After modification, the previous C# example looks like this:
&lt;code&gt;
[ComImport, Guid("??????????-????-????-????-???????????????"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOverrideMe
{
  [PreserveSig]
  Int32 overrideA();

  [PreserveSig]
  Int32 overrideB();
}

using System.Runtime.InteropServices;

public class overrideImpl :  IOverrideMe
{
   private static Int32 S_OK = unchecked((int)0x00000000);
   private const Int32 W_OVERRIDE_DO_DEFAULT = unchecked((Int32)0x8004FFFF);
   Int32 overrideA()
   {
       //Do something interesting.
      
      return S_OK;
   }

   Int32 overrideB()
   {
      return W_OVERRIDE_DO_DEFAULT;
   }
}
&lt;/code&gt;

The methods now return the HRESULT which the CLR forwards to the COM object without interpretation.  Generally speaking, I think that every time you import a custom COM interface (one that inherits from IUnknown) into .Net and you intend to pass that interface to a COM object you should also use the [PreserveSig] attribute and disable the runtime from interpreting the HRESULT.
</text>
  <last_update>2007-10-04T00:52:32.0150806Z</last_update>
  <source_title />
  <source_link />
  <comments />
  <references />
  <attachments />
</Content>